/*****************************************************************************
   *
   *  MPEG4DSP developped in IETR image lab
   *
   *
   *
   *              Jean-Francois NEZAN <jnezan@insa-rennes.Fr>
   *              Mickael Raulet <mraulet@insa-rennes.Fr>
   *              http://www.ietr.org/gro/IMA/th3/temp/index.htm
   *
   *  Based on the XviD MPEG-4 video codec
   *
   *
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or
   *  (at your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *  along with this program; if not, write to the Free Software
   *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
   *
   * $Id$
   *
   **************************************************************************/
#define VLC_ERROR (-1)
#define ESCAPE 3
#define ESCAPE1 6
#define ESCAPE2 14
#define ESCAPE3 15
#define LEVELOFFSET 32

typedef struct {
    short            code ;
    unsigned char   len ;
}   VLC ;


typedef struct {
    VLC     vlc ;
    EVENT   event ;
}   VLC_TABLE ;

/*****************************************************************************
   * common tables between encoder/decoder
   ****************************************************************************/
const VLC_TABLE     coeff_tab [2][102]
    = { /* intra = 0 */ {{{ 2, 2 }, { 0, 0, 1 }}, {{ 15, 4 }, { 0, 0, 2 }}, {{ 21, 6 }, { 0, 0, 3 }}
            , {{ 23, 7 }, { 0, 0, 4 }}, {{ 31, 8 }, { 0, 0, 5 }}, {{ 37, 9 }, { 0, 0, 6 }}, {{ 36, 9 }, { 0, 0, 7 }}
            , {{ 33, 10 }, { 0, 0, 8 }}, {{ 32, 10 }, { 0, 0, 9 }}, {{ 7, 11 }, { 0, 0, 10 }}, {{ 6, 11 }, { 0, 0, 11 }}
            , {{ 32, 11 }, { 0, 0, 12 }}, {{ 6, 3 }, { 0, 1, 1 }}, {{ 20, 6 }, { 0, 1, 2 }}, {{ 30, 8 }, { 0, 1, 3 }}
            , {{ 15, 10 }, { 0, 1, 4 }}, {{ 33, 11 }, { 0, 1, 5 }}, {{ 80, 12 }, { 0, 1, 6 }}, {{ 14, 4 }, { 0, 2, 1 }}
            , {{ 29, 8 }, { 0, 2, 2 }}, {{ 14, 10 }, { 0, 2, 3 }}, {{ 81, 12 }, { 0, 2, 4 }}, {{ 13, 5 }, { 0, 3, 1 }}
            , {{ 35, 9 }, { 0, 3, 2 }}, {{ 13, 10 }, { 0, 3, 3 }}, {{ 12, 5 }, { 0, 4, 1 }}, {{ 34, 9 }, { 0, 4, 2 }}
            , {{ 82, 12 }, { 0, 4, 3 }}, {{ 11, 5 }, { 0, 5, 1 }}, {{ 12, 10 }, { 0, 5, 2 }}, {{ 83, 12 }, { 0, 5, 3 }}
            , {{ 19, 6 }, { 0, 6, 1 }}, {{ 11, 10 }, { 0, 6, 2 }}, {{ 84, 12 }, { 0, 6, 3 }}, {{ 18, 6 }, { 0, 7, 1 }}
            , {{ 10, 10 }, { 0, 7, 2 }}, {{ 17, 6 }, { 0, 8, 1 }}, {{ 9, 10 }, { 0, 8, 2 }}, {{ 16, 6 }, { 0, 9, 1 }}
            , {{ 8, 10 }, { 0, 9, 2 }}, {{ 22, 7 }, { 0, 10, 1 }}, {{ 85, 12 }, { 0, 10, 2 }}, {{ 21, 7 }, { 0, 11, 1 }}
            , {{ 20, 7 }, { 0, 12, 1 }}, {{ 28, 8 }, { 0, 13, 1 }}, {{ 27, 8 }, { 0, 14, 1 }}, {{ 33, 9 }, { 0, 15, 1 }}
            , {{ 32, 9 }, { 0, 16, 1 }}, {{ 31, 9 }, { 0, 17, 1 }}, {{ 30, 9 }, { 0, 18, 1 }}, {{ 29, 9 }, { 0, 19, 1 }}
            , {{ 28, 9 }, { 0, 20, 1 }}, {{ 27, 9 }, { 0, 21, 1 }}, {{ 26, 9 }, { 0, 22, 1 }}
            , {{ 34, 11 }, { 0, 23, 1 }}, {{ 35, 11 }, { 0, 24, 1 }}, {{ 86, 12 }, { 0, 25, 1 }}
            , {{ 87, 12 }, { 0, 26, 1 }}, {{ 7, 4 }, { 1, 0, 1 }}, {{ 25, 9 }, { 1, 0, 2 }}, {{ 5, 11 }, { 1, 0, 3 }}
            , {{ 15, 6 }, { 1, 1, 1 }}, {{ 4, 11 }, { 1, 1, 2 }}, {{ 14, 6 }, { 1, 2, 1 }}, {{ 13, 6 }, { 1, 3, 1 }}
            , {{ 12, 6 }, { 1, 4, 1 }}, {{ 19, 7 }, { 1, 5, 1 }}, {{ 18, 7 }, { 1, 6, 1 }}, {{ 17, 7 }, { 1, 7, 1 }}
            , {{ 16, 7 }, { 1, 8, 1 }}, {{ 26, 8 }, { 1, 9, 1 }}, {{ 25, 8 }, { 1, 10, 1 }}, {{ 24, 8 }, { 1, 11, 1 }}
            , {{ 23, 8 }, { 1, 12, 1 }}, {{ 22, 8 }, { 1, 13, 1 }}, {{ 21, 8 }, { 1, 14, 1 }}, {{ 20, 8 }, { 1, 15, 1 }}
            , {{ 19, 8 }, { 1, 16, 1 }}, {{ 24, 9 }, { 1, 17, 1 }}, {{ 23, 9 }, { 1, 18, 1 }}, {{ 22, 9 }, { 1, 19, 1 }}
            , {{ 21, 9 }, { 1, 20, 1 }}, {{ 20, 9 }, { 1, 21, 1 }}, {{ 19, 9 }, { 1, 22, 1 }}, {{ 18, 9 }, { 1, 23, 1 }}
            , {{ 17, 9 }, { 1, 24, 1 }}, {{ 7, 10 }, { 1, 25, 1 }}, {{ 6, 10 }, { 1, 26, 1 }}, {{ 5, 10 }, { 1, 27, 1 }}
            , {{ 4, 10 }, { 1, 28, 1 }}, {{ 36, 11 }, { 1, 29, 1 }}, {{ 37, 11 }, { 1, 30, 1 }}
            , {{ 38, 11 }, { 1, 31, 1 }}, {{ 39, 11 }, { 1, 32, 1 }}, {{ 88, 12 }, { 1, 33, 1 }}
            , {{ 89, 12 }, { 1, 34, 1 }}, {{ 90, 12 }, { 1, 35, 1 }}, {{ 91, 12 }, { 1, 36, 1 }}
            , {{ 92, 12 }, { 1, 37, 1 }}, {{ 93, 12 }, { 1, 38, 1 }}, {{ 94, 12 }, { 1, 39, 1 }}
            , {{ 95, 12 }, { 1, 40, 1 }}}
        , /* intra = 1 */ {{{ 2, 2 }, { 0, 0, 1 }}, {{ 15, 4 }, { 0, 0, 3 }}, {{ 21, 6 }, { 0, 0, 6 }}
            , {{ 23, 7 }, { 0, 0, 9 }}, {{ 31, 8 }, { 0, 0, 10 }}, {{ 37, 9 }, { 0, 0, 13 }}, {{ 36, 9 }, { 0, 0, 14 }}
            , {{ 33, 10 }, { 0, 0, 17 }}, {{ 32, 10 }, { 0, 0, 18 }}, {{ 7, 11 }, { 0, 0, 21 }}
            , {{ 6, 11 }, { 0, 0, 22 }}, {{ 32, 11 }, { 0, 0, 23 }}, {{ 6, 3 }, { 0, 0, 2 }}, {{ 20, 6 }, { 0, 1, 2 }}
            , {{ 30, 8 }, { 0, 0, 11 }}, {{ 15, 10 }, { 0, 0, 19 }}, {{ 33, 11 }, { 0, 0, 24 }}
            , {{ 80, 12 }, { 0, 0, 25 }}, {{ 14, 4 }, { 0, 1, 1 }}, {{ 29, 8 }, { 0, 0, 12 }}
            , {{ 14, 10 }, { 0, 0, 20 }}, {{ 81, 12 }, { 0, 0, 26 }}, {{ 13, 5 }, { 0, 0, 4 }}
            , {{ 35, 9 }, { 0, 0, 15 }}, {{ 13, 10 }, { 0, 1, 7 }}, {{ 12, 5 }, { 0, 0, 5 }}, {{ 34, 9 }, { 0, 4, 2 }}
            , {{ 82, 12 }, { 0, 0, 27 }}, {{ 11, 5 }, { 0, 2, 1 }}, {{ 12, 10 }, { 0, 2, 4 }}, {{ 83, 12 }, { 0, 1, 9 }}
            , {{ 19, 6 }, { 0, 0, 7 }}, {{ 11, 10 }, { 0, 3, 4 }}, {{ 84, 12 }, { 0, 6, 3 }}, {{ 18, 6 }, { 0, 0, 8 }}
            , {{ 10, 10 }, { 0, 4, 3 }}, {{ 17, 6 }, { 0, 3, 1 }}, {{ 9, 10 }, { 0, 8, 2 }}, {{ 16, 6 }, { 0, 4, 1 }}
            , {{ 8, 10 }, { 0, 5, 3 }}, {{ 22, 7 }, { 0, 1, 3 }}, {{ 85, 12 }, { 0, 1, 10 }}, {{ 21, 7 }, { 0, 2, 2 }}
            , {{ 20, 7 }, { 0, 7, 1 }}, {{ 28, 8 }, { 0, 1, 4 }}, {{ 27, 8 }, { 0, 3, 2 }}, {{ 33, 9 }, { 0, 0, 16 }}
            , {{ 32, 9 }, { 0, 1, 5 }}, {{ 31, 9 }, { 0, 1, 6 }}, {{ 30, 9 }, { 0, 2, 3 }}, {{ 29, 9 }, { 0, 3, 3 }}
            , {{ 28, 9 }, { 0, 5, 2 }}, {{ 27, 9 }, { 0, 6, 2 }}, {{ 26, 9 }, { 0, 7, 2 }}, {{ 34, 11 }, { 0, 1, 8 }}
            , {{ 35, 11 }, { 0, 9, 2 }}, {{ 86, 12 }, { 0, 2, 5 }}, {{ 87, 12 }, { 0, 7, 3 }}, {{ 7, 4 }, { 1, 0, 1 }}
            , {{ 25, 9 }, { 0, 11, 1 }}, {{ 5, 11 }, { 1, 0, 6 }}, {{ 15, 6 }, { 1, 1, 1 }}, {{ 4, 11 }, { 1, 0, 7 }}
            , {{ 14, 6 }, { 1, 2, 1 }}, {{ 13, 6 }, { 0, 5, 1 }}, {{ 12, 6 }, { 1, 0, 2 }}, {{ 19, 7 }, { 1, 5, 1 }}
            , {{ 18, 7 }, { 0, 6, 1 }}, {{ 17, 7 }, { 1, 3, 1 }}, {{ 16, 7 }, { 1, 4, 1 }}, {{ 26, 8 }, { 1, 9, 1 }}
            , {{ 25, 8 }, { 0, 8, 1 }}, {{ 24, 8 }, { 0, 9, 1 }}, {{ 23, 8 }, { 0, 10, 1 }}, {{ 22, 8 }, { 1, 0, 3 }}
            , {{ 21, 8 }, { 1, 6, 1 }}, {{ 20, 8 }, { 1, 7, 1 }}, {{ 19, 8 }, { 1, 8, 1 }}, {{ 24, 9 }, { 0, 12, 1 }}
            , {{ 23, 9 }, { 1, 0, 4 }}, {{ 22, 9 }, { 1, 1, 2 }}, {{ 21, 9 }, { 1, 10, 1 }}, {{ 20, 9 }, { 1, 11, 1 }}
            , {{ 19, 9 }, { 1, 12, 1 }}, {{ 18, 9 }, { 1, 13, 1 }}, {{ 17, 9 }, { 1, 14, 1 }}, {{ 7, 10 }, { 0, 13, 1 }}
            , {{ 6, 10 }, { 1, 0, 5 }}, {{ 5, 10 }, { 1, 1, 3 }}, {{ 4, 10 }, { 1, 2, 2 }}, {{ 36, 11 }, { 1, 3, 2 }}
            , {{ 37, 11 }, { 1, 4, 2 }}, {{ 38, 11 }, { 1, 15, 1 }}, {{ 39, 11 }, { 1, 16, 1 }}
            , {{ 88, 12 }, { 0, 14, 1 }}, {{ 89, 12 }, { 1, 0, 8 }}, {{ 90, 12 }, { 1, 5, 2 }}
            , {{ 91, 12 }, { 1, 6, 2 }}, {{ 92, 12 }, { 1, 17, 1 }}, {{ 93, 12 }, { 1, 18, 1 }}
            , {{ 94, 12 }, { 1, 19, 1 }}, {{ 95, 12 }, { 1, 20, 1 }}}};

/* constants taken from momusys/vm_common/inlcude/max_level.h */
const unsigned char max_level_I [128]
    = { /* last = 0 */ 
    	27, 10, 5, 4, 3, 3, 3, 3, 2, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                , 0, 0, 0, 0, 0,
        /* last = 1 */ 
        8, 3, 2, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0
                , 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
                , 0, 0, 0, 0, 0
      };
                
const unsigned char max_level_P [128]
    = { /*last = 0 */
     	12, 6, 4, 3, 3, 3, 3, 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0
     	, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
      	/*last = 1 */
      	3, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
      	1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
      };
                
const unsigned char max_run_P [128]
    = { /* last = 0 */
    	0, 26, 10, 6, 2, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
    	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
     	/* intra = 0 */ 
        0, 40, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
      };
const unsigned char max_run_I [128]
	= { /* intra = 1 */ 
		0, 14, 9, 7, 3, 2, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
		0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        /* intra = 1 */
        0, 20, 6, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
      };
const VLC dc_lum_tab [] = {{ 0, 0 }, { 4, 3 }, { 3, 3 }, { 0, 3 }, { 2, 2 }, { 2, 2 }, { 1, 2 }, { 1, 2 }, };
